package server;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

/**
 * @author sxnan
 * @className Bootstrap
 * @description TODO
 * @date 2020/7/21
 */
public class Bootstrap {

    //监听网络的端口号
    private Integer port = 8080;

    public Integer getPort() {
        return port;
    }

    public void setPort(Integer port) {
        this.port = port;
    }

    public void start() throws IOException {

        loadServlet();

        /**
         * 定义一个线程池
         */
        int corePoolSize = 10;
        int maximumPoolSize = 50;
        long keepAliveTime = 100L;
        TimeUnit unit = TimeUnit.SECONDS;
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(50);
        ThreadFactory threadFactory = Executors.defaultThreadFactory();
        RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize,maximumPoolSize,keepAliveTime,unit,workQueue,threadFactory,handler);

        /**
         * 完成tomcat1.0版本
         * 实现：访问：http://localhost:8080，返回一个固定的字符页面”Hello Minicat!“；
         */
        //监听网络请求
        ServerSocket serverSocket = new ServerSocket(port);
        System.out.println("====================>>minicat start on port : "+port);
//        while (true){
//            Socket accept = serverSocket.accept();
//            OutputStream outputStream = accept.getOutputStream();
//            String data = "Hello Minicat!";
//            String returnStr = HttpProtocolUtil.getHeaderStr200(data.getBytes().length)+data;
//            outputStream.write(returnStr.getBytes());
//            accept.close();
//        }

        /**
         * 完成Mimicat2.0版本，封装Request对象和Response对象，返回Html静态资源文件
         */
//        while (true){
//            Socket accept = serverSocket.accept();
//            InputStream inputStream = accept.getInputStream();
//            Request request = new Request(inputStream);
//            Response response = new Response(accept.getOutputStream());
//            response.outputHtml(request.getUrl());
//            accept.close();
//        }

        /**
         * 3.0版本
         */
//        while (true) {
//            Socket accept = serverSocket.accept();
//            InputStream inputStream = accept.getInputStream();
//            Request request = new Request(inputStream);
//            Response response = new Response(accept.getOutputStream());
//            HttpServlet httpServlet = httpServletMap.get(request.getUrl());
//            if (httpServlet==null){
//                response.outputHtml(request.getUrl());
//            }else {
//                httpServlet.service(request,response);
//            }
//
//            accept.close();
//        }
/**
 * 多线程改造(不使用线程池)
 */
//        while (true) {
//            Socket accept = serverSocket.accept();
//            RequestProcessor requestProcessor = new RequestProcessor(accept, httpServletMap);
//            requestProcessor.start();
//        }

        /**
         * 多线程改造(使用线程池)
         */
        while (true) {
            Socket accept = serverSocket.accept();
            RequestProcessor requestProcessor = new RequestProcessor(accept, httpServletMap);
            threadPoolExecutor.execute(requestProcessor);
//            requestProcessor.start();
        }
    }

    private Map<String,HttpServlet> httpServletMap = new HashMap<>();



    /**
     * 加载web.xml配置文件并解析其中的内容
     */
    private void loadServlet() {
        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("web.xml");
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read(resourceAsStream);
            Element rootElement = document.getRootElement();
            List<Node> nodes = rootElement.selectNodes("//servlet");
            for (int i = 0; i < nodes.size(); i++) {
                Element element = (Element) nodes.get(i);
                // <servlet-name>lagou</servlet-name>
                Element servletNameElement = (Element) element.selectSingleNode("servlet-name");
                Element servletAppBaseElement = (Element) element.selectSingleNode("servlet-appBase");
                ClassLoader cl = new URLClassLoader(new URL[]{new File(servletAppBaseElement.getStringValue()).toURL()});
                String servletName = servletNameElement.getStringValue();
                //<servlet-class>server.LagouServlet</servlet-class>
                Element servletClassElement = (Element) element.selectSingleNode("servlet-class");
                String servletClass = servletClassElement.getStringValue();

                //根据servletName的值找到url-pattern
                Element servletMapping = (Element) rootElement.selectSingleNode("/web-app/servlet-mapping[servlet-name='"+servletName+"']");
                Element urlPatternElement = (Element) servletMapping.selectSingleNode("url-pattern");
                String urlPattern = urlPatternElement.getStringValue();
                httpServletMap.put(urlPattern, (HttpServlet) cl.loadClass(servletClass).newInstance());
            }
        } catch (DocumentException | ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }

    }

    /*入口程序*/
    public static void main(String[] args) {
        Bootstrap bootstrap = new Bootstrap();
        try {
            bootstrap.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
